package com.lagou.edu.filter;

import io.jsonwebtoken.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.RequestPath;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;


@Slf4j
@Component  // 让容器扫描到，等同于注册了
public class TokenFilter implements GlobalFilter, Ordered {



    // 令牌秘钥
    @Value("${token.secret}")
    private String secret;

    /**
     * 过滤器核心方法
     *
     * @param exchange 封装了request和response对象的上下文
     * @param chain    网关过滤器链（包含全局过滤器和单路由过滤器）
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 思路：获取token， 如果token是正确的， 就放行

        // 从上下文中取出request和response对象
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();


        // 只有info接口需要拦截
        Set<String> shouldFilter = new HashSet<>();
        shouldFilter.add("/user/info");

        RequestPath path = request.getPath();
        System.out.println(path);
        String dummyPath = path.subPath(0, 4).toString();
        System.out.println(dummyPath);
        if (shouldFilter.contains(dummyPath)) {
            // 假如是需要拦截的url， 则进行拦截

            // 获取token
            HttpCookie token = request.getCookies().getFirst("token");
            System.out.println(token);
            if (token == null || StringUtils.isBlank(token.getValue())) {
                // 设置为401， 返回
                return response.writeWith(unAuthorized(response));
            }

            // 存在暂时先直接放行
            try {
                Claims body = Jwts.parser()
                        .setSigningKey(secret)
                        .parseClaimsJws(token.getValue())
                        .getBody();
                String email = (String) body.get("email");
                if (StringUtils.isBlank(email)){
                    // 设置为401， 返回
                    return response.writeWith(unAuthorized(response));
                }

            } catch (Exception e) {
                log.error("token检查失败");
                // 设置为401， 返回
                return response.writeWith(unAuthorized(response));
            }

        }

        // 合法请求，放行，执行后续的过滤器
        return chain.filter(exchange);
    }

    private Mono<DataBuffer> unAuthorized(ServerHttpResponse response) {
        // 设置为401， 返回
        response.setStatusCode(HttpStatus.UNAUTHORIZED); // 状态码
        String data = "Request be denied!";
        return Mono.just(response.bufferFactory().wrap(data.getBytes()));
    }


    /**
     * 返回值表示当前过滤器的顺序(优先级)，数值越小，优先级越高
     *
     * @return
     */
    @Override
    public int getOrder() {
        return 0;
    }
}
